package com.peycash.fachada.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.peycash.common.Constantes;
import com.peycash.common.dto.ClienteDTO;
import com.peycash.common.dto.ClienteRegistroDTO;
import com.peycash.common.dto.NuevoClienteRequestDTO;
import com.peycash.common.dto.NuevoClienteResponseDTO;
import com.peycash.dominio.Cliente;
import com.peycash.dominio.Colonias;
import com.peycash.dominio.Domicilios;
import com.peycash.dominio.EstadosCliente;
import com.peycash.dominio.Municipios;
import com.peycash.fachada.ClienteOpFachada;
import com.peycash.fachada.FachadaException;
import com.peycash.servicio.ClienteServicio;
import com.peycash.servicio.ClientesPendientesServicio;
import com.peycash.servicio.ColoniaServicio;
import com.peycash.servicio.DomicilioServicio;
import com.peycash.servicio.MunicipioServicio;
import com.peycash.servicio.ServicioException;
import com.peycash.util.ClienteUtils;

@Service
public class ClienteOpFachadaImpl implements ClienteOpFachada {

	private final Logger LOGGER = LoggerFactory
			.getLogger(ClienteOpFachadaImpl.class);

	@Autowired
	private ClienteServicio servicioCliente;
	@Autowired
	private DomicilioServicio servicioDomicilio;
	@Autowired
	private ColoniaServicio servicioColonia;
	@Autowired
	private MunicipioServicio servicioMunicipio;
	@Autowired
	private ClientesPendientesServicio servicioClientesPendientes;
	
	
	@Override
	public List<String> findColoniasPorNombre(String nombre) throws FachadaException{
		try{
			List<String> list = servicioColonia.findNombresCoincidencia(nombre);
			return list;
		} catch (ServicioException e) {
			throw new FachadaException("Error en findColoniasPorNombre:"+e.getMessage(), e);
		}
	}
	
	@Override
	public void bajaTemporal(ClienteRegistroDTO dto) throws FachadaException{
		try {
			servicioCliente.bajaTemporal(dto);
		} catch (ServicioException e) {
			throw new FachadaException("Error en bajaTemporal:"+e.getMessage(), e);
		}
	}
	
	@Override
	public void llamarDespues(ClienteRegistroDTO dto) throws FachadaException{
		try {
			servicioCliente.llamarDespuesCliente(dto);
		} catch (ServicioException e) {
			throw new FachadaException("Error en llamarDespues:"+e.getMessage(), e);
		}
	}

	@Override
	public void saveCliente(ClienteRegistroDTO dto) throws FachadaException{
		try {
			servicioCliente.saveCliente(dto);
			servicioClientesPendientes.addClienteRegistrado(dto);
		} catch (ServicioException e) {
			throw new FachadaException("Error en saveCliente:"+e.getMessage(), e);
		}
	}
	

	@Override
	public long saveDomicilio(ClienteRegistroDTO dto)
			throws FachadaException {
		try {
			if (servicioColonia.existsCP(dto.getCp())) {
				/* se obtiene el municipio a partir del CP */
				int idMunicipioDelegacion = servicioColonia.getIdMunicipio(dto.getCp());
				Municipios m = new Municipios();
				m.setIdMunicipio(idMunicipioDelegacion);
				/* Se obtiene la colonia y/o se da de alta */
				long idColonia = servicioColonia.findIdColoniaByNombreAndCP(
						dto.getColonia(), dto.getCp());
				Colonias colonias = new Colonias();
				colonias.setIdColonia(idColonia);
				/* Se ajusta el domicilio */
				Domicilios d = new Domicilios();
				d.setCalleYNum(dto.getCalleyNo());
				d.setFechaModificacion(new Date());
				d.setUsuarioBd(dto.getUsuarioBd());
				d.setColonias(colonias);
				long idDomicilio = servicioDomicilio.save(d);
				return idDomicilio;
			} else {
				/* se busca el municipio o se da de alta */
				int idMunicipioDelegacion = servicioMunicipio
						.findIdMunicipioByNombreAndEstado(dto.getDelegacionMunicipio(),
								(short) dto.getIdEstado());
				Municipios m = new Municipios();
				m.setIdMunicipio(idMunicipioDelegacion);
				/* Se obtiene da de alta la colonia porque no existe el CP */
				long idColonia = servicioColonia.saveColonia(dto.getColonia(),
						idMunicipioDelegacion, dto.getCp());
				Colonias c = new Colonias();
				c.setIdColonia(idColonia);
				/* Se ajusta el domicilio */
				Domicilios d = new Domicilios();
				d.setCalleYNum(dto.getCalleyNo());
				d.setFechaModificacion(new Date());
				d.setUsuarioBd(dto.getUsuarioBd());
				d.setColonias(c);
				long idDomicilio = servicioDomicilio.save(d);
				return idDomicilio;

			}
		} catch (ServicioException e) {
			throw new FachadaException("Error en saveDomicilio:"
					+ e.getMessage(), e);
		}
	}

	@Override
	public List<ClienteDTO> findClientesPendientes() throws FachadaException {
		List<ClienteDTO> listPendientes;
		try {
			listPendientes = servicioCliente.findClientesPendientes();
			for (ClienteDTO dto : listPendientes) {
				updateCliente(dto.getNoCel());
			}
			listPendientes = servicioCliente.findClientesPendientesPorSistema();
		} catch (ServicioException e) {
			throw new FachadaException("Error en findClientesPendientes:"
					+ e.getMessage(), e);
		}
		return listPendientes;
	}

	@Override
	public boolean validaEntrada(NuevoClienteRequestDTO request) {
		if (request == null) {
			return false;
		}
		if (request.getNoCel() == null || request.getNoCel().isEmpty()) {
			return false;
		}
		if (request.getTipo() == null || request.getTipo().isEmpty()) {
			return false;
		}
		return true;
	}

	@Override
	public boolean validaFormatos(NuevoClienteRequestDTO request) {
		try {
			BigDecimal b = new BigDecimal(request.getNoCel());
		} catch (NumberFormatException ne) {
			return false;
		}
		if (!(request.getTipo().equals(Constantes.TIPO_CLIENTE_ENVIA) || request
				.getTipo().equals(Constantes.TIPO_CLIENTE_RECIBE))) {
			return false;
		}
		return true;
	}

	@Override
	public NuevoClienteResponseDTO creaResponseValido() {
		NuevoClienteResponseDTO response = new NuevoClienteResponseDTO();
		response.setCodigoRespuesta("00");
		response.setDescripcionRespuesta("OK");
		response.setR1("00");
		response.setR2("00");
		response.setR3("00");
		return response;
	}

	@Override
	public NuevoClienteResponseDTO creaResponseCamposIncompletos() {
		NuevoClienteResponseDTO response = new NuevoClienteResponseDTO();
		response.setCodigoRespuesta("11");
		response.setDescripcionRespuesta("CAMPOS OBLIGATORIOS FALTANTES");
		response.setR1("00");
		response.setR2("00");
		response.setR3("00");
		return response;
	}

	@Override
	public NuevoClienteResponseDTO creaResponseError() {
		NuevoClienteResponseDTO response = new NuevoClienteResponseDTO();
		response.setCodigoRespuesta("22");
		response.setDescripcionRespuesta("ERROR GENERAL, INTENTA MAS TARDE");
		response.setR1("00");
		response.setR2("00");
		response.setR3("00");
		return response;
	}

	@Override
	public NuevoClienteResponseDTO creaResponseFormatoInvalido() {
		NuevoClienteResponseDTO response = new NuevoClienteResponseDTO();
		response.setCodigoRespuesta("33");
		response.setDescripcionRespuesta("FORMATO DE CAMPOS INVALIDO");
		response.setR1("00");
		response.setR2("00");
		response.setR3("00");
		return response;
	}

	@Override
	public void addToContext(NuevoClienteRequestDTO request)
			throws FachadaException {
		try {
			String input_celEnvia = request.getNoCel();
			String tipo = request.getTipo();
			BigDecimal id = servicioCliente.findId(input_celEnvia);
			updateCliente(input_celEnvia);
			Map<String, String> paramMap = new HashMap<String, String>();
			paramMap.put(Constantes.INPUT_NO_CEL_ENVIA, input_celEnvia);
			paramMap.put(Constantes.INPUT_ID_CLIENTE, String.valueOf(id));
			paramMap.put(Constantes.INPUT_TIPO_CLIENTE, tipo);
			JSONObject jsonObject = new JSONObject(paramMap);
			String jsonString = jsonObject.toString();
			ClienteUtils.getInstace().agregaMensaje(jsonString);
		} catch (FachadaException e) {
			LOGGER.error("SIN INFO. DEL CLIENTE A AGREGAR A LA PLATAFORMA.::::"
					+ request.toString());
			throw new FachadaException(e.getMessage(), e);
		} catch (Exception e) {
			throw new FachadaException("Error en addToContext:"
					+ e.getMessage(), e);
		}
	}

	@Override
	public BigDecimal findId(String noCel) throws FachadaException {
		try {
			BigDecimal id = servicioCliente.findId(noCel);
			return id;
		} catch (ServicioException e) {
			throw new FachadaException("Error en findId:" + e.getMessage(), e);
		}
	}

	private void updateCliente(String input_celEnvia) throws FachadaException {
		try {
			BigDecimal id = findId(input_celEnvia);
			if (id == null) {
				throw new FachadaException(
						"Cliente inexistente. [PRE-REGISTRO]");
			}
			Cliente cliente = servicioCliente.findById(id);
			EstadosCliente e = new EstadosCliente();
			e.setIdEstadoCliente((byte) 4);
			cliente.setEstadosCliente(e);
			servicioCliente.updateCliente(cliente);
		} catch (ServicioException e) {
			throw new FachadaException("Error en updateCliente:"
					+ e.getMessage(), e);
		}

	}

}
